home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr47 / ucrasm27.zip / SOURCE.ZIP / SER1.ASM < prev    next >
Assembly Source File  |  1991-10-12  |  18KB  |  804 lines

  1. ;
  2. ; Routines to handle COM1 data transmission.
  3. ;
  4. ; COM1 refers to HARDWARE COM1 port which is located beginning at port
  5. ; address 3f8h and causes INT 0Ch.
  6. ;
  7. ;
  8. ; Released to the public domain.
  9. ; Created by Randall Hyde.
  10. ; Date: 8/11/90
  11. ;
  12. ;
  13. ; Useful equates:
  14. ;
  15. BIOSvars    =    40h
  16. Com1Adrs    =    0
  17. Com2Adrs    =    2
  18. ;
  19. BufSize        =    256            ;# of bytes in buffer.
  20. ;
  21. ;
  22. ; Serial port equates:
  23. ;
  24. Com1Port    =    3F8h
  25. Com1IER        =    3F9h
  26. Com1IIR        =    3FAh
  27. Com1LCR        =    3FBh
  28. Com1MCR        =    3FCh
  29. Com1LSR        =    3FDh
  30. Com1MSR        =    3FEh
  31. ;
  32. ;
  33. ; Register assignments:
  34. ;
  35. ; Interupt enable register (IER):
  36. ;
  37. ;        If one:
  38. ; bit 0-    Enables received data available interrupt.
  39. ; bit 1-    Enables transmitter holding register empty interrupt.
  40. ; bit 2-    Enables receiver line status interrupt.
  41. ; bit 3-    Enables the modem status interrupt.
  42. ; bits 4-7-    Always set to zero.
  43. ;
  44. ; Interrupt ID Register (IIR):
  45. ;
  46. ; bit 0-    No interrupt is pending (interrupt pending if zero).
  47. ; bits 1,2-    Binary value denoting source of interrupt:
  48. ;            00-Modem status
  49. ;            01-Transmitter Hold Register Empty
  50. ;            10-Received Data Available
  51. ;            11-Receiver line status
  52. ; bits 3-7    Always zero.
  53. ;
  54. ;
  55. ; Line Control Register (LCR):
  56. ;
  57. ; bits 0,1-    Word length (00=5, 01=6, 10=7, 11=8 bits).
  58. ; bit 2-    Stop bits (0=1, 1=2 stop bits [1-1/2 if 5 data bits]).
  59. ; bit 3-    Parity enabled if one.
  60. ; bit 4-    0 for odd parity, 1 for even parity (assuming bit 3 = 1).
  61. ; bit 5-    1 for stuck parity.
  62. ; bit 6-    1=force break.
  63. ; bit 7-    1=Divisor latch access bit.  0=rcv/xmit access bit.
  64. ;
  65. ; Modem Control Register (MCR):
  66. ;
  67. ; bit 0-    Data Terminal Ready (DTR)
  68. ; bit 1-    Request to send (RTS)
  69. ; bit 2-    OUT 1
  70. ; bit 3-    OUT 2
  71. ; bit 4-    Loop back control.
  72. ; bits 5-7-    Always zero.
  73. ;
  74. ; Line Status Register (LSR):
  75. ;
  76. ; bit 0-    Data Ready
  77. ; bit 1-    Overrun error
  78. ; bit 2-    Parity error
  79. ; bit 3-    Framing error
  80. ; bit 4-    Break Interrupt
  81. ; bit 5-    Transmitter holding register is empty.
  82. ; bit 6-    Transmit shift register is empty.
  83. ; bit 7-    Always zero.
  84. ;
  85. ; Modem Status Register (MSR):
  86. ;
  87. ; bit 0-    Delta CTS
  88. ; bit 1-    Delta DSR
  89. ; bit 2-    Trailing edge ring indicator
  90. ; bit 3-    Delta carrier detect
  91. ; bit 4-    Clear to send
  92. ; bit 5-    Data Set Ready
  93. ; bit 6-    Ring indicator
  94. ; bit 7-    Data carrier detect
  95. ;
  96. ;
  97. ;
  98. ;
  99. ;
  100. ;
  101. ;
  102. StdGrp        group    StdLib, StdData
  103. ;
  104. ;
  105. ;
  106. ;
  107. StdData        segment    para public 'sldata'
  108. ;
  109. int0Cofs    equ    es:[30h]
  110. int0Cseg    equ    es:[32h]
  111. int0cVec    dd    ?        ;Holds old int 0ch vector.
  112. InHead        dw    InpBuf
  113. InTail        dw    InpBuf
  114. InpBuf        db    Bufsize dup (?)
  115. InpBufEnd    equ    this byte
  116. ;
  117. OutHead        dw    OutBuf
  118. OutTail        dw    OutBuf
  119. OutBuf        db    BufSize dup (?)
  120. OutBufEnd    equ    this byte
  121. ;
  122. i8259a        db    0        ;8259a interrupt enable register.
  123. TestBuffer    db    0        ;1 means we are transmitting out of
  124. ;                    ; the transmit buffer.  0 means the
  125. ;                    ; transmitter register is empty and
  126. ;                    ; we can store data directly to it.
  127. StdData        ends
  128. ;
  129. ;
  130. ;
  131. stdlib        segment    para public 'slcode'
  132.         assume    cs:StdGrp
  133. ;
  134. ;
  135. ;
  136. ; sl_Com1Baud: Set the COM1 port baud rate
  137. ; AX = baud rate (110, 150, 300, 600, 1200, 2400, 4800, 9600, 19200)
  138. ;
  139.         public    sl_Com1Baud
  140. sl_Com1Baud    proc    far
  141.         push    ax
  142.         push    dx
  143.         cmp    ax, 9600
  144.         ja    Set19200
  145.         je    Set9600
  146.         cmp    ax, 2400
  147.         ja    Set4800
  148.         je    Set2400
  149.         cmp    ax, 600
  150.         ja    Set1200
  151.         je    Set600
  152.         cmp    ax, 150
  153.         ja    Set300
  154.         je    Set150
  155.         mov    ax, 1047        ;Default to 110 baud
  156.         jmp    short SetPort
  157. ;
  158. Set150:        mov    ax, 768
  159.         jmp    short SetPort
  160. ;
  161. Set300:        mov    ax, 384
  162.         jmp    short SetPort
  163. ;
  164. Set600:        mov    ax, 192
  165.         jmp    short SetPort
  166. ;
  167. Set1200:    mov    ax, 96
  168.         jmp    short SetPort
  169. ;
  170. Set2400:    mov    ax, 48
  171.         jmp    short SetPort
  172. ;
  173. Set4800:    mov    ax, 24
  174.         jmp    short SetPort
  175. ;
  176. Set9600:    mov    ax, 12
  177.         jmp    short SetPort
  178. ;
  179. Set19200:    mov    ax, 6
  180. SetPort:    mov    dx, ax            ;Save baud value.
  181.         call    far ptr sl_GetLCRCom1
  182.         push    ax            ;Save old divisor bit value.
  183.         or    al, 80h            ;Set divisor select bit.
  184.         call    far ptr sl_SetLCRCom1
  185.         mov    ax, dx            ;Get baud rate divisor value.
  186.         mov    dx, Com1Port
  187.         out    dx, al
  188.         inc     dx
  189.         mov    al, ah
  190.         out    dx, al
  191.         mov    dx, Com1LCR
  192.         pop    ax
  193.         call    far ptr sl_SetLCRCom1    ;Restore divisor bit value.
  194.         pop    dx
  195.         pop    ax
  196.         ret
  197. sl_Com1Baud    endp
  198. ;
  199. ;
  200. ; sl_Com1Stop:
  201. ; Set the number of stop bits.
  202. ;
  203. ; AL=1 for one stop bit, 2 for two stop bits.
  204. ;
  205.         public    sl_com1Stop
  206. sl_com1Stop    proc    far
  207.         push    ax
  208.         push    dx
  209.         dec    ax
  210.         shl    ax, 1            ;position into bit #2
  211.         shl    ax, 1
  212.         mov    ah, al
  213.         mov    dx, Com1LCR
  214.         in    al, dx
  215.         and     al, 11111011b        ;Mask out Stop Bits bit
  216.         or    al, ah            ;Mask in new # of stop bits.
  217.         out    dx, al
  218.         pop    dx
  219.         pop    ax
  220.         ret
  221. sl_com1Stop    endp
  222. ;
  223. ;
  224. ; sl_com1size: Sets word size on the com1 port.
  225. ; AX = 5, 6, 7, or 8 which is the number of bits to set.
  226. ;
  227.         public    sl_com1size
  228. sl_com1size    proc    far
  229.         push    ax
  230.         push    dx
  231.         sub    al, 5
  232.         cmp    al, 3
  233.         jbe    Okay
  234.         mov    al, 3            ;Default to eight bits.
  235. Okay:        mov    ah, al
  236.         mov    dx, com1LCR
  237.         in    al, dx
  238.         and    al, 11111100b        ;Mask out old word size
  239.         or    al, ah            ;Mask in new word size
  240.         out    dx, al
  241.         pop    dx
  242.         pop    ax
  243.         ret
  244. sl_com1size    endp
  245. ;
  246. ;
  247. ; sl_com1parity: Turns parity on/off, selects even/odd parity, or stuck parity.
  248. ; ax contains the following:
  249. ;
  250. ; bit 0-    1 to enable parity, 0 to disable.
  251. ; bit 1-    0 for odd parity, 1 for even (only valid if bit 0 is 1).
  252. ; bit 2-    Stuck parity bit.  If 1 and bit 0 is 1, then the parity bit
  253. ;        is always set to the inverse of bit 1.
  254. ;
  255.         public    sl_com1parity
  256. sl_com1parity    proc    far
  257.         push    ax
  258.         push    dx
  259. ;
  260.         shl    ax, 1
  261.         shl    ax, 1
  262.         shl    ax, 1
  263.         and    ax, 00111000b        ;Mask out other data.
  264.         mov    ah, al
  265.         mov    dx, com1LCR
  266.         in    al, dx
  267.         and    al, 11000111b
  268.         or    al, ah
  269.         out    dx, al
  270.         pop    dx
  271.         pop    ax
  272.         ret
  273. sl_com1parity    endp
  274. ;
  275. ;
  276. ;****************************************************************************
  277. ;
  278. ; Polled I/O:
  279. ;
  280. ;
  281. ; sl_ReadCom1-    Reads a character from COM1 and returns that character in
  282. ;        the AL register.  Synchronous call, meaning it will not
  283. ;        return until a character is available.
  284. ;
  285.         public    sl_ReadCom1
  286. sl_ReadCom1    proc    far
  287.         push    dx
  288.         call    far ptr sl_GetLCRCom1
  289.         push    ax            ;Save divisor latch access bit.
  290.         and    al, 7fh            ;Select normal port.
  291.         call    far ptr sl_SetLCRCom1
  292.         mov    dx, com1LSR
  293. WaitForChar:    call    far ptr sl_GetLSRCom1
  294.         test    al, 1            ;Data Available?
  295.         jz    WaitForChar
  296.         mov    dx, com1Port
  297.         in    al, dx
  298.         mov    dl, al            ;Save character
  299.         pop    ax            ;Restore divisor access bit.
  300.         call    far ptr sl_SetLCRCom1
  301.         mov    al, dl            ;Restore output character.
  302.         pop    dx
  303.         ret
  304. sl_ReadCom1    endp
  305. ;
  306. ;
  307. ;
  308. ; sl_WriteCom1-    Writes the character in AL to the com1 port.
  309. ;
  310.         public    sl_WriteCom1
  311. sl_WriteCom1    proc    far
  312.         push    dx
  313.         push    ax
  314.         mov    dl, al            ;Save character to output
  315.         call    far ptr sl_GetLCRCom1
  316.         push    ax            ;Save divisor latch access bit.
  317.         and    al, 7fh            ;Select normal port.
  318.         call    far ptr sl_SetLCRCom1
  319. WaitForXmtr:    call    far ptr sl_GetLSRCom1
  320.         test    al, 00100000b        ;Xmtr buffer empty?
  321.         jz    WaitForXmtr
  322.         mov    al, dl            ;Get output character.
  323.         mov    dx, Com1Port
  324.         out    dx, al
  325.         pop    ax            ;Restore divisor access bit.
  326.         call    far ptr sl_SetLCRCom1
  327.         pop    ax
  328.         pop    dx
  329.         ret
  330. sl_WriteCom1    endp
  331. ;
  332. ;
  333. ;
  334. ; sl_TstInpCom1-Returns AL=0 if a character is not available at the com1 port.
  335. ;        Returns AL=1 if a character is available.
  336. ;
  337.         public    sl_TstInpCom1
  338. sl_TstInpCom1    proc    far
  339.         push    dx
  340.         mov    dx, com1LSR
  341.         in    al, dx
  342.         and     al, 1
  343.         pop    dx
  344.         ret
  345. sl_TstInpCom1    endp
  346. ;
  347. ;
  348. ; sl_TstOutCom1-Returns AL=1 when it's okay to send another character to
  349. ;        the transmitter.  Returns zero if the transmitter is full.
  350. ;
  351.         public    sl_TstOutCom1
  352. sl_TstOutCom1    proc    far
  353.         push    dx
  354.         mov    dx, com1LSR
  355.         in    al, dx
  356.         test    al, 00100000b
  357.         mov    al, 0
  358.         jz    toc1
  359.         inc    ax
  360. toc1:        pop    dx
  361.         ret
  362. sl_TstOutCom1    endp
  363. ;
  364. ;
  365. ; sl_GetLSRCom1-Returns the LSR in al:
  366. ;
  367. ; AL:
  368. ;    bit 0-    Data Ready
  369. ;    bit 1-    Overrun error
  370. ;    bit 2-    Parity error
  371. ;    bit 3-    Framing error
  372. ;    bit 4-    Break interrupt
  373. ;    bit 5-    Xmtr holding register is empty.
  374. ;    bit 6-    Xmtr shift register is empty.
  375. ;    bit 7-    Always zero.
  376. ;
  377.         public    sl_GetLSRCom1
  378. sl_GetLSRCom1    proc    far
  379.         push    dx
  380.         mov    dx, com1LSR
  381.         in    al, dx
  382.         pop    dx
  383.         ret
  384. sl_GetLSRCom1    endp
  385. ;
  386. ;
  387. ; sl_GetMSRCom1-Returns the modem status register in AL
  388. ;
  389. ; AL:
  390. ;    bit 0-    Delta clear to send
  391. ;    bit 1-    Delta data set ready
  392. ;    bit 2-    Trailing edge ring indicator
  393. ;    bit 3-    Delta data carrier detect
  394. ;    bit 4-    Clear to send (CTS)
  395. ;    bit 5-    Data set ready (DSR)
  396. ;    bit 6-    Ring indicator (RI)
  397. ;    bit 7-    Data carrier detect (DCD)
  398. ;
  399.         public    sl_GetMSRCom1
  400. sl_GetMSRCom1    proc    far
  401.         push    dx
  402.         mov    dx, com1MSR
  403.         in    al, dx
  404.         pop    dx
  405.         ret
  406. sl_GetMSRCom1    endp
  407. ;
  408. ;
  409. ; sl_SetMCRCom1-Writes the data in AL to the modem control register.
  410. ; sl_GetMCRCom1-Reads the data from the modem control register into AL.
  411. ;
  412. ; AL:
  413. ;    bit 0-    Data terminal ready (DTR)
  414. ;    bit 1-    Request to send (RTS)
  415. ;    bit 2-    Out 1
  416. ;    bit 3-    Out 2
  417. ;    bit 4-    Loop
  418. ;    bits 5-7 (must be zero)
  419. ;
  420.         public    sl_SetMCRCom1
  421. sl_SetMCRCom1    proc    far
  422.         push    dx
  423.         mov    dx, com1MCR
  424.         out    dx, al
  425.         pop    dx
  426.         ret
  427. sl_SetMCRCom1    endp
  428. ;
  429.         public    sl_GetMCRCom1
  430. sl_GetMCRCom1    proc    far
  431.         push    dx
  432.         mov    dx, com1MCR
  433.         in    al, dx
  434.         pop    dx
  435.         ret
  436. sl_GetMCRCom1    endp
  437. ;
  438. ;
  439. ;
  440. ; sl_GetLCRCom1- Reads the value from the line control register into AL.
  441. ; sl_SetLCRCom1- Writes the value in AL to the line control register.
  442. ;
  443. ; AL:
  444. ;    bits 0,1-    Word length selection
  445. ;    bit 2-        Number of stop bits
  446. ;    bit 3-        Parity Enable
  447. ;    bit 4-        Even parity select
  448. ;    bit 5-        Stuck parity
  449. ;    bit 6-        Set Break
  450. ;    bit 7-        Divisor latch access bit
  451. ;
  452.         public    sl_GetLCRCom1
  453. sl_GetLCRCom1    proc    far
  454.         push    dx
  455.         mov    dx, com1LCR
  456.         in    al, dx
  457.         pop    dx
  458.         ret
  459. sl_GetLCRCom1    endp
  460. ;
  461.         public    sl_SetLCRCom1
  462. sl_SetLCRCom1    proc    far
  463.         push    dx
  464.         mov    dx, com1LCR
  465.         out    dx, al
  466.         pop    dx
  467.         ret
  468. sl_SetLCRCom1    endp
  469. ;
  470. ;
  471. ; sl_GetIIRCom1-Reads the interrupt indentification register and returns its
  472. ;        value in AL.
  473. ;
  474. ; AL:
  475. ;    bit 0-        0 if interrupt pending, 1 if no interrupt.
  476. ;    bits 1,2-    Interrupt ID (highest priority).
  477. ;    bits 3-7-    Always zero.
  478. ;
  479. ; Interrupt ID
  480. ; bit 2  1    Source                Reset by
  481. ;     ----    -----------------------------    ------------------------------
  482. ;     0  0    CTS, DSR, RI            Reading the MSR
  483. ;     0  1    Xmtr holding register empty    Reading IIR or writing to xmtr
  484. ;     1  0    Receiver data available        Reading rcvr buffer
  485. ;     1  1    Overrun, parity, framing, or    Reading the LSR.
  486. ;        break
  487. ;
  488. ;
  489.         public    sl_GetIIRCom1
  490. sl_GetIIRCom1    proc    far
  491.         push    dx
  492.         mov    dx, com1IIR
  493.         in    al, dx
  494.         pop    dx
  495.         ret
  496. sl_GetIIRCom1    endp
  497. ;
  498. ;
  499. ; sl_GetIERCom1-Reads the IER and returns it in AL.
  500. ; sl_SetIERCom1-Stores the value in AL into the IER.
  501. ;
  502. ; AL:
  503. ;    bit 0-    Enable data available interrupt.
  504. ;    bit 1-    Enable xmtr holding register empty interrupt.
  505. ;    bit 2-    Enable receive line status interrupt.
  506. ;    bit 3-    Enable modem status interrupt
  507. ;    bits 4-7  Always zero.
  508. ;
  509.         public    sl_GetIERCom1
  510. sl_GetIERCom1    proc    far
  511.         push    dx
  512.         call    sl_GetLCRCom1
  513.         push    ax            ;Save divisor access bit.
  514.         and    al, 7fh            ;Address the IER.
  515.         call    sl_SetLCRCom1
  516.         mov    dx, com1IER
  517.         in    al, dx
  518.         mov    dl, al            ;Save for now
  519.         pop    ax
  520.         call    sl_SetLCRCom1        ;Restore divisor latch
  521.         mov    al, dl            ;Restore IER value
  522.         pop    dx
  523.         ret
  524. sl_GetIERCom1    endp
  525. ;
  526. ;
  527.         public    sl_SetIERCom1
  528. sl_SetIERCom1    proc    far
  529.         push    dx
  530.         push    ax
  531.         mov    ah, al            ;Save value to output
  532.         call    sl_GetLCRCom1        ;Get and save divsor access
  533.         push    ax            ;bit.
  534.         and    al, 7fh            ;Address the IER.
  535.         call    sl_SetLCRCom1
  536.         mov    al, ah
  537.         mov    dx, com1IER
  538.         out    dx, al
  539.         pop    ax            ;Restore divisor latch bit.
  540.         call    sl_SetLCRCom1
  541.         pop    ax
  542.         pop    dx
  543.         ret
  544. sl_SetIERCom1    endp
  545. ;
  546. ;
  547. ;****************************************************************************
  548. ;
  549. ; Interrupt-driven Serial I/O
  550. ;
  551. ;
  552. ; sl_InitCom1Int-    Initializes the hardware to use interrupt-driven I/O
  553. ;            for COM1:
  554. ;
  555.         public    sl_InitCom1Int
  556. sl_InitCom1Int    proc    far
  557.         pushf            ;Save interrupt disable flag.
  558.         push    es
  559.         push    ax
  560.         push    dx
  561. ;
  562. ; Turn off the interrupts while we're screwing around here.
  563. ;
  564.         cli
  565. ;
  566. ; Save old interrupt vector.
  567. ;
  568.         xor    ax, ax        ;Point at interrupt vectors
  569.         mov    es, ax
  570.         mov    ax, Int0Cofs    ;Get ofs int 0ch vector.
  571.         mov    word ptr StdGrp:int0cVec, ax
  572.         mov    ax, Int0Cseg    ;Get seg int 0ch vector.
  573.         mov    word ptr StdGrp:int0cVec+2, ax
  574. ;
  575. ; Point int 0ch vector at our interrupt service routine:
  576. ;
  577.         mov    ax, cs
  578.         mov    Int0Cseg, ax
  579.         mov    ax, offset stdgrp:Com1IntISR
  580.         mov    Int0Cofs, ax
  581. ;
  582. ; Clear any pending interrupts:
  583. ;
  584.         call    far ptr sl_GetLSRCom1    ;Clear Receiver line status
  585.         call    far ptr sl_GetMSRCom1    ;Clear CTS/DSR/RI Interrupts
  586.         call    far ptr sl_GetIIRCom1    ;Clear xmtr empty interrupt
  587.         mov    dx, Com1Port
  588.         in    al, dx            ;Clear data available intr.
  589. ;
  590. ; Clear divisor latch access bit.  WHILE OPERATING IN INTERRUPT MODE, THE
  591. ; DIVISOR ACCESS LATCH BIT MUST ALWAYS BE ZERO.  If for some horrible reason
  592. ; you need to change the baud rate in the middle of a transmission (or while
  593. ; the interrupts are enabled) clear the interrupt flag, do your dirty work,
  594. ; clear the divisor latch bit, and finally restore interrupts.
  595. ;
  596.         call    far ptr sl_getLCRCom1
  597.         and    al, 7fh
  598.         call    far ptr sl_SetLCRCom1
  599. ;
  600. ;
  601. ; Enable the receiver and transmitter interrupts
  602. ;
  603.         mov    al, 3        ;Enable rcv/xmit interrupts
  604.         call    far ptr sl_SetIERCom1
  605. ;
  606. ; Must set the OUT2 line for interrupts to work.
  607. ; Also sets DTR and RTS active.
  608. ;
  609.         mov    al, 00001011b
  610.         call    far ptr sl_SetMCRCom1
  611. ;
  612. ; Activate the COM1 (int 0ch) bit in the 8259A interrupt controller chip.
  613. ;
  614.         in    al, 21h
  615.         mov    StdGrp:i8259a, al    ;Save interrupt enable bit.
  616.         and    al, 0efh    ;Bit 4=IRQ 4 = INT 0Ch
  617.         out    21h, al
  618. ;
  619.         pop    dx
  620.         pop    ax
  621.         pop    es
  622.         popf            ;Restore interrupt disable flag.
  623.         ret
  624. sl_InitCom1Int    endp
  625. ;
  626. ;
  627. ; sl_IntsOffCom1- Disconnects the interrupt system and shuts off interrupt
  628. ;          activity at the COM1: port.
  629. ;
  630. ;    Warning!  This routine assumes that interrupts are currently active
  631. ;          due to a call to sl_InitCom1Int.  If you call this guy
  632. ;          w/o first calling sl_InitCom1Int you will probably crash
  633. ;          the system.  Furthermore, this routine makes the (rather
  634. ;          presumptuous) assumption that no one else has patched into
  635. ;          the INT 0Ch vector since SL_InitCom1Int was called.
  636. ;
  637.         public    sl_IntsOffCom1
  638. sl_IntsOffCom1    proc    far
  639.         pushf
  640.         push    es
  641.         push    dx
  642.         push    ax
  643. ;
  644.         cli            ;Don't allow interrupts while messing
  645.         xor    ax, ax        ; with the interrupt vectors.
  646.         mov    es, ax        ;Point at interrupt vectors.
  647. ;
  648. ; First, turn off the interrupt source:
  649. ;
  650.         call    far ptr sl_GetMCRCom1
  651.         and    al, 3            ;Mask out OUT 2 bit (masks ints)
  652.         call    far ptr sl_SetMCRCom1
  653. ;
  654.         in    al, 21h            ;Get 8259a ier
  655.         and    al, 0efh        ;Clear IRQ 4 bit.
  656.         mov    ah, StdGrp:i8259a        ;Get our saved value
  657.         and    ah, 1000b        ;Mask out com1: bit (IRQ 4).
  658.         or    al, ah            ;Put bit back in.
  659.         out    21h, al
  660. ;
  661. ; Restore the interrupt vector:
  662. ;
  663.         mov    ax, word ptr StdGrp:Int0cVec
  664.         mov    Int0Cofs, ax
  665.         mov    ax, word ptr StdGrp:Int0cVec+2
  666.         mov    Int0Cseg, ax
  667. ;
  668.         pop    ax
  669.         pop    dx
  670.         pop    es
  671.         popf
  672.         ret
  673. sl_IntsOffCom1    endp
  674. ;
  675. ;----------------------------------------------------------------------------
  676. ;
  677. ; Com1IntISR- Interrupt service routine for COM1:
  678. ;
  679. Com1IntISR    proc    far
  680.         push    ax
  681.         push    bx
  682.         push    dx
  683. TryAnother:    mov    dx, Com1IIR
  684.         in    al, dx            ;Get id
  685.         test    al, 1            ;Any interrupts left?
  686.         jnz     IntRtn
  687.         test    al, 100b
  688.         jnz    ReadCom1
  689.         test    al, 10b
  690.         jnz    WriteCom1
  691. ;
  692. ; Bogus interrupt?
  693. ;
  694.         call    sl_GetLSRCom1        ;Clear receiver line status
  695.         call    sl_GetMSRCom1        ;Clear modem status.
  696.         jmp    TryAnother
  697. ;
  698. IntRtn:        mov    al, 20h            ;Acknowledge interrupt to the
  699.         out    20h, al            ; 8259A interrupt controller.
  700.         pop    dx
  701.         pop    bx
  702.         pop    ax
  703.         iret
  704. ;
  705. ; Handle incoming data here:
  706. ; (Warning: This is a critical region.  Interrupts MUST BE OFF while executing
  707. ;  this code.  By default, interrupts are off in an ISR.  DO NOT TURN THEM ON
  708. ;  if you modify this code).
  709. ;
  710. ReadCom1:    mov    dx, Com1Port
  711.         in    al, dx            ;Get the input char
  712.         mov    bx, StdGrp:InHead
  713.         mov    StdGrp:[bx], al
  714.         inc    bx
  715.         cmp    bx, offset stdgrp:InpBufEnd
  716.         jb    NoInpWrap
  717.         mov    bx, offset stdgrp:InpBuf
  718. NoInpWrap:    cmp    bx, StdGrp:InTail
  719.         je    TryAnother
  720.         mov    StdGrp:InHead, bx
  721.         jmp    TryAnother
  722. ;
  723. ;
  724. ; Handle outgoing data here (This is also a critical region):
  725. ;
  726. WriteCom1:      mov    bx, StdGrp:OutTail
  727.         cmp    bx, StdGrp:OutHead
  728.         jne    OutputChar
  729. ;
  730. ; If head and tail are equal, simply set the TestBuffer variable to zero
  731. ; and quit.  If they are not equal, then there is data in the buffer and
  732. ; we should output the next character.
  733. ;
  734.         mov    StdGrp:TestBuffer, 0
  735.         jmp    TryAnother
  736. ;
  737. ; The buffer pointers are not equal, output the next character down here.
  738. ;
  739. OutputChar:     mov    al, StdGrp:[bx]
  740.         mov    dx, Com1Port
  741.         out    dx, al
  742.         inc    bx
  743.         cmp    bx, offset stdgrp:OutBufEnd
  744.         jb      NoOutWrap
  745.         mov    bx, offset stdgrp:OutBuf
  746. NoOutWrap:    mov    StdGrp:OutTail, bx
  747.         jmp    TryAnother
  748. Com1IntISR    endp
  749. ;
  750. ;
  751. ;----------------------------------------------------------------------------
  752. ;
  753. ; Routines to read/write characters in serial buffers.
  754. ;
  755.         public    sl_InCom1
  756. sl_InCom1    proc    far
  757.         pushf                ;Save interrupt flag
  758.         push    bx
  759.         sti                ;Make sure interrupts are on.
  760. TstInLoop:    mov    bx, StdGrp:InTail
  761.         cmp    bx, StdGrp:InHead
  762.         je    TstInLoop
  763.         mov    al, StdGrp:[bx]        ;Get next char.
  764.         cli                ;Turn off ints while adjusting
  765.         inc    bx            ; buffer pointers.
  766.         cmp    bx, offset stdgrp:InpBufEnd
  767.         jne    NoWrap2
  768.         mov    bx, offset stdgrp:InpBuf
  769. NoWrap2:    mov    StdGrp:InTail, bx
  770.         pop    bx
  771.         popf                ;Restore interrupt flag.
  772.         ret
  773. sl_InCom1    endp
  774. ;
  775. ;
  776.         public    sl_OutCom1
  777. sl_OutCom1    proc    far
  778.         pushf
  779.         cli                ;No interrupts now!
  780.         cmp    StdGrp:TestBuffer, 0    ;Write directly to serial chip?
  781.         jnz    BufferItUp
  782.         call    far ptr sl_WriteCom1    ;Output to port
  783.         mov    StdGrp:TestBuffer, 1    ;Must buffer up next char.
  784.         popf
  785.         ret
  786. ;
  787. BufferItUp:    push    bx
  788.         mov    bx, StdGrp:OutHead
  789.         mov    StdGrp:[bx], al
  790.         inc    bx
  791.         cmp    bx, offset stdgrp:OutBufEnd
  792.         jne    NoWrap3
  793.         mov    bx, offset stdgrp:OutBuf
  794. NoWrap3:    cmp    bx, StdGrp:OutTail
  795.         je    NoSetTail
  796.         mov    StdGrp:OutHead, bx
  797. NoSetTail:    pop    bx
  798.         popf
  799.         ret
  800. sl_OutCom1    endp
  801. ;
  802. stdlib        ends
  803.         end
  804.